<?php
//MVC框架类
class Framework{
	//启动项目
	public static function run(){
		self::init(); //初始化
		self::registerAutoLoad(); //注册自动加载
		self::extend();   //扩展功能
		self::dispatch(); //请求分发
	}
	//初始化
	private static function init(){
		//开启调试时，显示错误报告
		if(APP_DEBUG){
			ini_set('display_errors',1);
			error_reporting(E_ALL);
		}else{
			ini_set('display_errors',0);
			error_reporting(0);
		}
		//设置常量供项目内使用
		define('DS', DIRECTORY_SEPARATOR); //路径分隔符
		define('ROOT', getcwd().DS); //项目根目录
		define('APP_PATH', ROOT.'app'.DS); //应用目录
		define('FRAMEWORK_PATH', ROOT.'framework'.DS); //框架目录
		define('LIBRARY_PATH', FRAMEWORK_PATH.'library'.DS);//类库目录
		define('PUBLIC_PATH', ROOT.'public'.DS); //公开目录
		define('COMMON_PATH', APP_PATH.'common'.DS); //公共目录
		//载入函数库
		require FRAMEWORK_PATH.'function.php';
		//获取p、c、a参数
		list($p,$c,$a) = self::getParams();
		define('PLATFORM', strtolower($p));
		define('CONTROLLER', strtolower($c));
		define('ACTION', strtolower($a));
		//拼接平台、控制器、模型、视图路径
		define('PLATFORM_PATH', APP_PATH.PLATFORM.DS); //平台目录
		define('CONTROLLER_PATH', PLATFORM_PATH.'controller'.DS); //控制器目录
		define('MODEL_PATH', PLATFORM_PATH.'model'.DS); //模型目录
		define('VIEW_PATH', PLATFORM_PATH.'view'.DS); //视图目录
		//视图路径
		define('COMMON_VIEW', VIEW_PATH.'common'.DS);
		define('ACTION_VIEW', VIEW_PATH.CONTROLLER.DS.ACTION.'.html');
	}
	//注册自动加载
	private static function registerAutoLoad(){
		spl_autoload_register(function($class_name){
			$class_name = ucwords($class_name); //自动转换类名首字母大写
			if(strpos($class_name, 'Controller')){
				$target = CONTROLLER_PATH."$class_name.class.php";
				if(is_file($target)){
					require $target;
				}else{
					E('您的访问参数有误！');
				}
			}elseif(strpos($class_name, 'Model')){
				require MODEL_PATH."$class_name.class.php";
			}else{
				require LIBRARY_PATH."$class_name.class.php";
			}
		});
	}
	//扩展功能
	private static function extend(){
		//配置时区
		date_default_timezone_set(C('DEFAULT_TIMEZONE'));
		//设置HttpOnly
		C('PHPSESSID_HTTPONLY') && ini_set('session.cookie_httponly', 1);
		//Session入库
		C('SESSION_DB') && new SessionDB();
		//配置 mbstring 扩展内置字符集
		mb_internal_encoding('UTF-8');
	}
	//请求分发
	private static function dispatch(){
		$c = CONTROLLER.'Controller';
		$a = ACTION.'Action';
		//实现请求分发
		$Controller = new $c(); //实例化控制器
		$Controller->$a(); //调用操作
	}
	//获取请求参数
	private static function getParams(){
		//获取URL参数
		$p = I('p','get','string','home');
		$c = I('c','get','string','index');
		$a = I('a','get','string','index');
		//获取pathinfo
		$pathinfo = self::getPathinfo();
		//定义常量表示 URL Rewrite 开关
		define('URL_REWRITE', (bool)$pathinfo);
		//开启URL Rewrite时，从pathinfo获取参数
		if(URL_REWRITE){
			$params = self::getPathinfoParams($pathinfo);
			//进行路由规则匹配
			$start = 0; //取出参数的起始下标
			if(isset($params[0]) && ($roule=C('URL_MAP_RULES')) && isset($roule[$params[0]])){
				list($p,$c,$a) = explode('/', $roule[$params[0]]);
				$start = (count($params)%2 > 0) ? 1 : 0; //根据参数个数，自动取出后面的参数
			}
			//将pathinfo参数保存到$_GET中
			for($len=count($params);$start<$len;$start+=2){
				if(isset($params[$start])){
					$_GET[$params[$start]] = isset($params[$start+1]) ? $params[$start+1] : '';
				}
			}
		}
		//正则验证参数，要求以字母开头，后面跟0~20个 字母/数字/下划线 字符
		foreach(array($p,$c,$a) as $v) {
			preg_match('/^[A-Za-z]\w{0,20}$/',$v) || E('请求参数包含特殊字符！');
		}
		return array($p,$c,$a);
	}
	//获取pathinfo
	private static function getPathinfo(){
		return I('PATH_INFO','server','string', I('ORIG_PATH_INFO','server','string'));
	}
	//从pathinfo中获取参数，进行路由匹配
	private static function getPathinfoParams($pathinfo){
		//过滤URL后缀
		$suffix = C('URL_SUFFIX');
		$len = strlen($suffix);
		if(substr($pathinfo,-$len)==$suffix){
			$pathinfo = substr($pathinfo, 0, strlen($pathinfo)-$len);
		}
		//将pathinfo转换为数组
		return explode('/', trim($pathinfo, '/'));
	}
}